#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QThread>
#include "include/qt_node/qt_ros_node.hpp" // 引入我们的节点头文件
#include "qt_node/ros_proxy.hpp"
//#include "rclcpp/rclcpp.hpp" // 在节点头文件里面包含了

int main(int argc, char *argv[])
{
    // 1. 初始化ROS 2
    rclcpp::init(argc, argv);

    // 2. 使用 std::make_shared 来管理节点的生命周期
    auto ros_node = std::make_shared<QtROSNode>("qt_ros_node");
    auto ros_proxy = std::make_shared<ROSProxy>(); // Proxy活在主线程

    // 3. 创建一个QThread来运行ROS事件循环
    QThread* ros_thread = new QThread();

    // 4. 将我们的节点 "移动" 到新线程。这不是物理移动，而是设置其事件亲和性。
    ros_node->moveToThread(ros_thread);

    QGuiApplication app(argc, argv);

    // 5.1 方向1: QML -> Proxy -> ROS Node (发布消息)
    //     当Proxy发射doPublish信号时，调用ros_node的publishMessage槽
    QObject::connect(ros_proxy.get(), &ROSProxy::doPublish,
                     ros_node.get(), &QtROSNode::publishMessage);

    // 5.2 方向2: ROS Node -> Proxy -> QML (接收消息)
    //     当ros_node发射messageReceived信号时，调用Proxy的onMessageReceived槽
    QObject::connect(ros_node.get(), &QtROSNode::messageReceived,
                     ros_proxy.get(), &ROSProxy::onMessageReceived);

    // 6. 当线程启动后，再去调用 startTimer 槽
    QObject::connect(ros_thread, &QThread::started, ros_node.get(), &QtROSNode::startTimer);

    // 7. 当Qt应用即将退出时，安全地关闭ROS 2
    QObject::connect(&app, &QGuiApplication::aboutToQuit, &app, [ros_node, ros_thread]() {
        RCLCPP_INFO(ros_node->get_logger(), "Application is about to quit. Shutting down ROS.");
        rclcpp::shutdown();
        ros_thread->quit(); // 告诉线程事件循环停止
        if (!ros_thread->wait(2000)) { // 等待最多2秒
            RCLCPP_WARN(ros_node->get_logger(), "ROS thread did not terminate gracefully. Forcing termination.");
            ros_thread->terminate();
            ros_thread->wait();
        }
        delete ros_thread;
    });

    // 8. 启动ROS线程
    ros_thread->start();

    QQmlApplicationEngine engine;

    // 修正这里的URL，使其与诊断出的真实路径完全匹配
    const QUrl url(QStringLiteral("qrc:/qt_node/qml/Main.qml"));

    // 9. 将我们的ros_proxy代理暴露给QML，这样QML就可以调用它的方法
    engine.rootContext()->setContextProperty("rosProxy", ros_proxy.get());

    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [url](QObject *obj, const QUrl &objUrl) {
                         if (!obj && url == objUrl)
                             QCoreApplication::exit(-1);
                     }, Qt::QueuedConnection);

    engine.load(url);

    return app.exec();
}
